import { StatusBar } from 'expo-status-bar';
import { Text, StyleSheet, View, TouchableOpacity } from 'react-native';

// 基本类型，只能在tsx文件里面写
// 1、会给提示，指定了n为number类型，若下面为字符串类型，则会报错；
// 但是要是直接赋值‘abc’也能打印出来abc
// let n:number = 100;
// n=123;
// console.log(n);
// 2、数组里面的类型全都得是number类型的，一个不是都会报错
// let arr:number[]=[1,2,'a'];
// 3、object不能这么写
// let obj:object={
//   name:'ll',
//   age:20,
// }
// obj.a=100;
// 4、对象类型的该怎么写{name:type,...}
// 类型别名，自定义个类型的，通用的类型，将来在任何地方都能使用
// type user={ name: string, age: number };
// let obj: user = {
//     name:'ll',
//     age:20,
// };
// 5、作业一类型检查 data里面的内容类型检查必须得是规定的，不能随便加{}
// type opt={
//   title:string,
//   content:string
// }
// let data:opt={
//   title:'title',
//   content:'content'
// }
// 如果不写title：title,默认就是重名的
// let d={title,content};

// 6、元组,当数组里面类型不一样的时候，用元组来进行表达
// let arr1:[string,number]=['1',2];
// 7、any,不确定是什么类型，表示任意类型，有时候用any是为不报错
// 普通数组
// let arr2:any[]=[1,2,'222',{title:12}]
// 8、枚举enum
// 默认就是数字枚举0，1，2，3往后排的,要是指定是多少的话就都指定才行
// 也可以指定成字符串，字符串的话一定要指定,不指定就报错
// enum D{
//   up='20',
//   right='30',
//   down=50,
//   left=60
// }
// console.log(D.left);
// enum Res{
//   success,
//   fail
// }
// console.log(Res.success);

// // 在函数中应用
// const fn = (n:number,n2:number):number=>{
//   // 1、前面指明了有number类型的返回值，就必须有;要是类型不对也会报错
//   // 没有返回值的话，可以将number换成void
//   console.log(123);
//   return n+n2;
// }
// const fn1 = (n:number,n2:number):void=>{
//   // 2、没有返回值的话，void
//   console.log(123);
// }
// // 3、可选参数都要放到到最后一位，第三个参数n3?:number代表这个参数可写可不写
// const fn2 = (n:number,n2:number,n3?:number):void=>{
//   // 没有返回值的话，void
//   console.log(123);
// }
// fn2(1,2)
// // 4、最后一个可选参数为函数，而且该函数没有返回值
// const fn3 = (n:number,n2:number,cb?:()=>void):void=>{
//   // 没有返回值的话，可以将number换成void
//   console.log(123)
// }
// fn3(1,2);
// // 5、剩余参数也是放到最后，...n无论打印什么都会成为数组类型，后面都可以是任意传的，
// const fn4=(a:number,...n:number[]):number=>{
//   console.log(n);
//   return 1;
// }
// fn4(1,2,3,4,5);

type Prop = {
  title: string,
  id: number
}

const Header = (props: Prop) => {
  return <Text>
    {props.title}-----{props.id + 100}
  </Text>
}

// 1、联合类型,两种类型都可以来使用，在函数当中，参数都可以，确定是两者之间的一个就可以使用
// let data:number|string='abc';
// data=100;
// data=true;//报错
// type类型别名，自定义个类型的，通用的类型，将来在任何地方都能使用
// 当用到的地方比较多时，可以用来提取出去，只有是这种基本数据类型才能用这种type,不能用接口
// type dataType=number|string;
// let data:dataType='abc';
// data=100;
// data=true;//报错

// 2、交叉类型
type A = {
  width: number
}
type B = {
  height: number
} & A;
let shape: B = {
  height: 10,
  width: 10
}

// 3、接口---属性接口,接口名一般都大写

// 接口和类型别名都能使用的时候，优先选择接口
// interface User{
//   name:string,
//   age:number
// }

// type user={
//   name:string,
//   age:number,
// }
// let user1:User={
//   name:'h11',
//   age:18
// }
// let user2:user={
//   name:'h11',
//   age:18
// }
// // 4、类继承接口  implements（实现）
// interface User {
//   name: string,
//   age: number
// }
// class Person implements User{
//   name='h1ll'
//   age=20
// }
// // 5、接口可以继承，type是不可以被继承的
// interface Shape {
//   color: string;
// }
// interface Square extends Shape {
//   sideLength: number;
// }

// // 类型断言（值 as 类型）
// let squ={} as Square;
// squ.color='red';
// squ.sideLength=100;

// // 1、访问修饰符，public、private（只能类内使用）、protected
// class User{
//   static a=100;
//   say(){}
//   name='11'
// }
// // 静态方法
// console.log(User.a)
// console.log(new User().name)

// 2、泛型，箭头函数用这种泛型的方法
// 是指在定义函数、接口或类的时候，不预先指定具体的类型，而在使用的时候再指定类型的一种特性
const add=<T,>(n:T): T=>{
  return n;
}
add<string>('aaa');
// // 一般多的时候才会使用泛型，少的话用any即可
// function identity<T,>(arg: T): T {
//   return arg;
// }
// identity<string>('params1')//调用的时候加一个尖括号来指定数据类型
// identity<number>(100)
// // 3、普通装饰器（无参数），装饰器就是一个函数，修饰后面类，把函数的功能注入到类中
// // 注意装饰器上下两个不能加分号（；），一加分号就断了
// 只要装饰器修饰类，那么在类的原型当中就有了这个函数，可以执行
// function addUrl(target: any) {
//   target.prototype.url='https://'
//   console.log('hello Word!');
// }
// function helloWord(target: any) {
//   console.log('hello Word!');
// }
// @addUrl
// @helloWord
// class HelloWordClass {
//   name='hh'
// }
// console.log(new HelloWordClass().url);

// // 装饰器工厂 （带参数）
// function helloWord(p:string) {
//   return function (target) { //  这才是真正装饰器
//       target.prototype.url='https://'
//        console.log(p)
//   }
// }
// @helloWord('hello')
// class HelloWordClass {

// }
// console.log(new HelloWordClass().url);



export default function App() {

  return (
    <View style={styles.container}>
      <Header title='TS' id={888} />
      <Text>hello TS</Text>
    </View>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#ccc'
  },
})




// 写作业布局时，层级结构越少越好，能用弹性盒用弹性盒
// 默认主轴方向---纵向，应该给<TouchableOpacity>加事件，事件给一大个盒子加，变化的透明度，上下左右居中
// 盒子高度不要写高度，别设高度，body的高度不要设置，具体里面的高度可以设置，由内容撑开，
// 高度 弹性盒